#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#include <netinet/in.h>
#include <sys/epoll.h>
#include <arpa/inet.h>
#include <pthread.h>
#include <signal.h>

#define SERVER_PORT  12345
#define BUFF_SIZE 2048  //缓存区大小
#define HEAD_LEN 4      //头部长度4字节
#define HEAD_ID_LEN 2   //头部id长度2字节
#define HEAD_LEN_LEN 2  //头部长度字段2字节



extern int global_epoll_fd;
extern int wakeup_pipe[2];

static int event_count = 1024;
extern volatile sig_atomic_t  stop_server;
// 信号处理器：收到 SIGINT/SIGTERM 时设置退出标志
void handle_signal(int signo);
int init_wakeup_pipe();


//接受状态
enum RecvStage{
    NO_RECV = 0,  //未接受
    HEAD_RECVING,
    BODY_RECVING,
};

//头部buffer
typedef struct{
    //缓存接受的头部信息
    char* buf;
    //头部总长度
    size_t data_len;
    //头部偏移量
    size_t offset;
}head_buf_t;


//数据buffer,用来存储接受或者发送的数据
typedef struct {
    //数据类型id, 比如1001表示登录，1002表示聊天等。
    uint16_t type;
    //接受或发送缓存
    char* buf;
    //数据总长度
    size_t data_len;
    //已接受或发送的偏移量
    size_t offset;
}data_buf_t;

//发送数据节点
typedef struct send_node {
    data_buf_t *send_buf;  // 数据缓冲区
    struct send_node *next; 
} send_node_t;

//发送队列
typedef struct {
    //发送队列头部
    send_node_t* head;
    //互斥锁，保证多线程访问安全
    pthread_mutex_t send_que_lock;
} send_que_t;

//会话节点表示一个连接
typedef struct{
    //文件描述符
    int fd;
    //存储接受的数据包体内容
    data_buf_t * data_buf;
    //存储未接受完整的头部
    head_buf_t * head_buf;
    //发送队列
    send_que_t *send_que;
    //接受阶段,0未开始后接受，1接受头部，2接受包体
    enum RecvStage  recv_stage;
} session_t;


head_buf_t * malloc_head_buf(int head_len);
void dealloc_head_buf(head_buf_t* head_buf);

data_buf_t * malloc_data_buf(int type_id, int data_len);
void dealloc_data_buf(data_buf_t* data_buf);

send_node_t * malloc_send_node(int type_id, int data_len);
void dealloc_send_node(send_node_t* send_node);

send_que_t* malloc_send_que();
void dealloc_send_que(send_que_t* send_que);

session_t * session_create(int fd);
void dealloc_session(session_t* session);
void session_destroy(session_t* conn, int epoll_fd);

//设置非阻塞
extern void set_nonblocking(int fd);
int create_and_bind();

//消息队列
void enqueue_node(send_que_t * q, send_node_t * node, int epoll_fd, int fd, uint32_t evs);
ssize_t async_send(session_t* sess,  int epoll_fd, uint32_t evs, size_t msg_type, size_t body_len, char* buf);
void handle_epollout(int epoll_fd, int fd, send_que_t *q);